﻿using DingTalkAgent.SqlData;
using DingTalkAgent.Web.Common;
using Li.DingTalk.Helper;
using Li.DingTalk.Model.Contacts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using DingTalkAgent.Web.Models;
using DingTalkAgent.Model;
using System.IO;
using System.Collections;
using Newtonsoft.Json;
using System.Text;

namespace DingTalkAgent.Web.Controllers
{
    //[Common.Filter.AuthorizeFilter]
    public class EmployeeController : BaseController
    {
        DingTalkAgent.SqlData.Department dal = new SqlData.Department();
        T_EmployeeRepository _employeeDal = new T_EmployeeRepository();

        #region 首页数据
        // GET: Employee
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 获取部门列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public JsonResult GetDepartmentList(string id)
        {
            if (string.Equals(id, "#"))
                id = "0";
            List<JsonTree> tree = new List<JsonTree>();
            //通过本地查找
            var result = JsonHelpers.DataSetToList<department>(_employeeDal.GetDepartmentList(id), 0);

            //通过钉钉查询
            //var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);// "ding4d58972322cf686735c2f4657eb6378f");
            //var result = GetDepartments(access_token, id);

            if (result != null && result.Count > 0)
            {
                foreach (var item in result)
                {
                    var children = JsonHelpers.DataSetToList<department>(_employeeDal.GetDepartmentList(item.id.ToString()), 0);
                    tree.Add(new JsonTree { id = item.id.ToString(), text = item.name, state = children != null && children.Count > 0 ? "closed" : "open" });
                }
                //动态加载节点，一次只加载父节点的数据
                var json = tree.Select(o => new
                {
                    id = o.id,
                    text = o.text,
                    state = o.state,
                    children = o.state == "closed"
                }).ToList();

                return Json(json, JsonRequestBehavior.AllowGet);
            }
            return Json(tree, JsonRequestBehavior.AllowGet);
        }

        private departmentlist GetDepartments(string token, string pid)
        {
            return Li.DingTalk.Model.Contacts.departmentHD.list(token, pid);
        }

        public JsonResult GetEmployeeList()
        {
            var page = this.Parse<Int32>(Request, "page", 1);
            var rows = this.Parse<Int32>(Request, "rows", 10);
            var pid = this.Parse<Int32>(Request, "pid", 1);
            var query = this.Parse<String>(Request, "query", null);
            int offset = (page - 1) * rows;
            //通过本地数据库查找
            var ds = _employeeDal.GetEmployeeList(offset, rows, pid.ToString(), query);

            //通过钉钉查找
            //var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);
            //var result = Li.DingTalk.Model.Contacts.userHD.Getdepartmentmemberlist(access_token, pid, offset, rows);

            T_UserDTO dto = new T_UserDTO();

            if (ds != null && ds.Tables != null && ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
            {
                dto.rows = JsonHelpers.DataSetToList<DingTalkAgent.Model.users>(ds, 0);
                dto.page = page;
                dto.pageSize = rows;
                dto.records = Convert.ToInt32(ds.Tables[1].Rows[0][0]);
                return Json(dto, JsonRequestBehavior.AllowGet);
            }
            return Json(dto, JsonRequestBehavior.AllowGet);
        }
        #endregion

        #region 新增、编辑、删除暂时用不到，不作修改
        public ActionResult Add()
        {
            return View(new userInfo());
        }

        public ActionResult Edit(string id)
        {
            var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);
            var item = Li.DingTalk.Model.Contacts.userHD.GetUserInfo(access_token, id.ToString());
            return View("Add", item);
        }

        public string Save(departmentmemberuserlists model)
        {
            var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);
            if (!string.IsNullOrEmpty(model.userid))
            {
                //修改本地

                //同步钉钉
                var result = Li.DingTalk.Model.Contacts.userHD.Updatemember(access_token, new updatememberstructural { userid = model.userid, name = model.name, mobile = model.mobile });
                return result.ErrCode == 0 ? "ok" : "false";
            }
            else
            {
                //同步到钉钉
                var result = Li.DingTalk.Model.Contacts.userHD.Createmember(access_token, new creatememberstructural { name = model.name, mobile = model.mobile });

                //在本地数据库中新增
                if (result.IsOK())
                {
                    //_employeeDal.SaveEmployee(result, 0);
                }
                return result.ErrCode == 0 ? "ok" : "false";
            }
        }

        public string Delete(string ids)
        {
            //先输出本地数据库的数据
            var result = _employeeDal.DelectEmployee(ids);
            if (result > 0)
            {
                //同步输出的数据到钉钉
                var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);
                return Li.DingTalk.Model.Contacts.userHD.batchdeletion(access_token, new batchdeletionstructural { useridlist = ids.Split(',') }).ErrCode == 0 ? "ok" : "isSysFalse";
            }

            return "false";
        }
        #endregion

        #region 同步
        /// <summary>
        /// 同步主方法
        /// </summary>
        /// <returns></returns>
        public JsonResult SysData()
        {

            var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);

            //1.因为无法一步获取部门详情，第一步先获取部门所有的id
            List<long> _ids = new List<long>();
            _ids.Add(1);
            GetAllDepartment(access_token, "1", ref _ids);

            //2.通过部门id获取部门详情
            List<departmentMS> _departments = new List<departmentMS>();
            foreach (var id in _ids)
            {
                var department = Li.DingTalk.Model.Contacts.departmentHD.Getdepartmentlist(access_token, id.ToString());
                if (department.IsOK())
                    _departments.Add(department);
            }

            //3.通过一级部门获取所有员工详情
            var _department = _departments.Where(o => o.id == 1);//获取一级部门所有id
            var _employees = new List<departmentmemberuserlists>();
            if (_department != null)
            {
                int index = 0;
                var employee = new departmentmemberlists();
                do
                {
                    index++;
                    employee = Li.DingTalk.Model.Contacts.userHD.Getdepartmentmemberlist(access_token, 1, (index - 1) * 100, 100);
                    if (employee.IsOK())
                        _employees.AddRange(employee.userlist);
                }
                while (employee.hasMore);
            }

            //4.同步数据
            SysDataToDB(_departments, _employees);

            return Json(new { status = true, msg = "同步成功！" }, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 获取所有层级的部门信息
        /// </summary>
        /// <param name="areaID"></param>
        /// <param name="areaIDList"></param>
        private void GetAllDepartment(string access_token, string pid, ref List<long> ids)
        {
            if (ids == null)
                ids = new List<long>();
            var result = Li.DingTalk.Model.Contacts.departmentHD.GetDepartmentIds(access_token, pid);
            if (result.IsOK())
            {
                foreach (var item in result.sub_dept_id_list)
                {
                    ids.Add(item);
                    GetAllDepartment(access_token, item.ToString(), ref ids);
                }
            }
        }
        /// <summary>
        /// 同步数据到数据库
        /// </summary>
        /// <param name="_departments">部门信息</param>
        /// <param name="_employees">员工信息</param>
        private void SysDataToDB(List<departmentMS> _departments, List<departmentmemberuserlists> _employees)
        {
            //同步部门信息
            Task department_Task = new Task(() =>
            {
                try
                {
                    _employeeDal.SysDepartments(_departments);
                }
                catch (Exception ex)
                {

                }
            });
            department_Task.Start();
            //同步员工信息
            Task user_Task = new Task(() =>
            {
                try
                {
                    _employeeDal.SysEmployees(_employees);
                }
                catch (Exception ex)
                {
                }
            });
            user_Task.Start();
        }
        #endregion

        #region 钉钉数据更新回调

        /// <summary>
        /// 注册回调
        /// </summary>
        public void Register_call_back()
        {
            var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);
            var _callBackData = new
            {
                call_back_tag = "user_add_org,user_modify_org,user_leave_org,org_admin_add,org_admin_remove,org_dept_create,org_dept_modify,org_dept_remove".Split(','),//需要监听的事件，
                //user_add_org:用户增加,user_modify_org:用户更改,user_leave_org:离职,org_admin_add:用户被设置为管理员,org_admin_remove:用户被取消管理员,org_dept_create:创建部门
                //org_dept_modify：部门更改，org_dept_remove：删除部门
                token = ConfigHelper.FetchValue("Token"),//加解密需要用到的token，随机填写
                aes_key =ConfigHelper.FetchValue("AesKey"),//数据加密密钥。用于回调数据的加密，长度固定为43个字符，从a-z, A-Z, 0-9共62个字符中选取,
                url = "http://common.yndingtalk.com/Employee/Call_Back"//接收事件回调的url
            };
            var result = Li.DingTalk.Model.Contacts.userHD.Register_Call_Back(access_token, JsonHelpers.ToJson(_callBackData));
            //写入日志
            Discuz.Common.LogInfo.Log("DingTalk_CallBack", "注册钉钉同步数据Url，接口返回参数【" + JsonHelpers.ToJson(result) + "】");
        }

        /// <summary>
        /// 回调地址  需要返回经过加密后的字符串“success”的json数据，否则钉钉服务器将认为url不合法，从而不予推送。
        /// </summary>
        /// <returns></returns>
        public JsonResult Call_Back()
        {
            //获取请求参数
            var signature =  this.Parse<String>(Request, "signature", "");//钉钉的加密签名，signature结合了开发者填写的token、请求中的timestamp、nonce参数、加密的消息体
            var timestamp =  this.Parse<String>(Request, "timestamp", "");//时间戳
            var nonce = this.Parse<String>(Request, "nonce", "");//随机字符串
            
            // 获取post body里的参数
            var encrypt = GetPostParam();
            //
            var callBackReq = JsonHelpers.ToEntity<callBackReq>(encrypt);

            //获取token
            var token = ConfigHelper.FetchValue("Token");

            //构造钉钉加解密类
            DingTalkCryptHelper helper = new DingTalkCryptHelper(token, ConfigHelper.FetchValue("AesKey"), ConfigHelper.FetchValue("CorpID")); // "ding4d58972322cf686735c2f4657eb6378f");//token为钉钉开放平台上，开发者设置的token，aesKey为钉钉开放台上，开发者设置的EncodingAESKey,suiteKey为钉钉开放平台上，开发者设置的suiteKey

            //解密
            var plainText = string.Empty;
            var result = helper.DecryptMsg(signature, timestamp, nonce, callBackReq.encrypt, ref plainText);

            //同步数据
            if (!string.IsNullOrEmpty(plainText))
            {
                try
                {
                    var access_token = Li.DingTalk.AccessTokenContainer.TryGetToken(_view_account.corpId);
                    var _encrypt = JsonHelpers.ToEntity<Encrypt>(plainText);
                    var _employees = new List<userInfo>();
                    var _departments = new List<departmentMS>();

                    switch (_encrypt.eventType)
                    {
                        case "user_add_org"://添加
                        case "user_modify_org"://修改
                        case "org_admin_add"://设置为管理员
                        case "org_admin_remove"://取消管理员
                            foreach (var id in _encrypt.userId)
                            {
                                var user = Li.DingTalk.Model.Contacts.userHD.GetUserInfo(access_token, id);
                                if (user.IsOK())
                                    _employees.Add(user);
                            }
                            break;
                        case "user_leave_org"://员工离职

                            break;
                        case "org_dept_create"://创建部门
                        case "org_dept_modify"://修改部门
                            foreach (var id in _encrypt.deptId)
                            {
                                var department = Li.DingTalk.Model.Contacts.departmentHD.Getdepartmentlist(access_token, id);
                                if (department.IsOK())
                                    _departments.Add(department);
                            }
                            break;
                        case "org_dept_remove"://删除部门

                            break;
                    }
                }
                catch (Exception ex) { }
            }

            string sEncryptMsg = string.Empty;//解密后的消息

            var json = new callBackResponse
            {
                msg_signature = "",//消息体签名
                timeStamp = TimeHelper.GetTimestamp(DateTime.Now),//时间戳
                nonce = RandomHelper.GetRandomString(6),//随机字符串
                encrypt = "success" //“success”加密字符串
            };

            //签名消息体
            if (DingTalkCryptHelper.GenerateSignature(token, json.timeStamp, json.nonce, sEncryptMsg, ref signature) == 0)
            {
                if (helper.EncryptMsg(json.encrypt, json.timeStamp, json.nonce, ref sEncryptMsg, ref signature) == 0)
                    json.encrypt = sEncryptMsg;
                json.msg_signature = signature;
            }

            return Json(json, JsonRequestBehavior.AllowGet);
        }

        private string GetPostParam()
        {
            if ("POST" == Request.RequestType)
            {
                Stream sm = Request.InputStream;//获取post正文
                int len = (int)sm.Length;//post数据长度
                byte[] inputByts = new byte[len];//字节数据,用于存储post数据
                sm.Read(inputByts, 0, len);//将post数据写入byte数组中
                sm.Close();//关闭IO流

                //**********下面是把字节数组类型转换成字符串**********
                return Encoding.UTF8.GetString(inputByts);//转为String
            }
            return "";
        }

        #endregion
    }
}